/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.farmcode.web.generation;

import com.farmcode.api.runtime.*;
import com.farmcode.api.runtime.metadata.ObjectInfo;
import com.farmcode.api.runtime.regex.MatchContext;
import com.farmcode.base.dao.DAOException;
import com.farmcode.base.manager.FacadeException;
import com.farmcode.console.api.business.ProjectManager;
import com.farmcode.console.api.business.custom.*;
import com.farmcode.console.api.model.Match;
import com.farmcode.console.api.model.Project;
import com.farmcode.console.api.model.Property;
import com.farmcode.console.api.model.Template;
import com.farmcode.web.generation.objectinfo.ProcedureBackingBean;
import com.farmcode.web.generation.objectinfo.TablesBackingBean;
import com.farmcode.web.generation.objectinfo.ViewsBackingBean;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ValueChangeEvent;
import javax.inject.Named;
//import org.primefaces.model.TreeNode;s

/**
 *
 * @author Oscar Ivan Prado
 */
@Named(value = "codeGeneratorBackingBean")
@RequestScoped
public class CodeGeneratorBackingBean extends BaseCodeGenerator {

    private static final Logger logger = Logger.getLogger(CodeGeneratorBackingBean.class.getName());
    
    @EJB
    private ProjectManager projectManager;
    @EJB
    private ExtProjectManager extProjectManager;
    @EJB
    private ExtPropertyManager extPropertyManager;
    @EJB
    private ExtTemplateManager extTemplateManager;
    @EJB
    private ExtMatchManager extMatchManager;
    @EJB
    private ExtMatchContextManager extMatchContextManager;
    @EJB
    private RuntimeServerAPI runtimeServerAPI;
    private String projectName;
    private List<Project> projects;
    private List<Property> parameters;
    private List<Property> variables;
    private List<Template> templates;

//    private TreeNode tablesRoot; 
    
    /** Creates a new instance of CodeGeneratorBackingBean */
    public CodeGeneratorBackingBean() {
    }

    public void onCompile() throws FacadeException {
        TemplateCollection collection = new TemplateCollection();
        for (Template template : getTemplates()) {
            TemplateInfo templateInfo = new TemplateInfo(template.getName(), template.getPath(), template.getPath(), template.getExtension());
            collection.add(templateInfo);
            getMathContextByTemplate(template, templateInfo);
        }
        try {
            
            List<ObjectInfo> tables = getSession().getValue(TablesBackingBean.OBJECTS_INFO);
            List<ObjectInfo> views = getSession().getValue(ViewsBackingBean.OBJECTS_INFO);
            List<ObjectInfo> procedures = getSession().getValue(ProcedureBackingBean.OBJECTS_INFO);
            
            FARMCodeContext context = getContext();
            Metadata metadata = new Metadata();
            if (tables != null) {
                metadata.getObjectInfos().add(tables);
            }
            if (views != null) {
                metadata.getObjectInfos().add(views);
            }

            if (procedures != null) {
                metadata.getObjectInfos().add(procedures);
            }

            context.put(FARMCodeContext.TEMPLATES, collection);
            context.put(FARMCodeContext.METADATA, metadata);
            if (metadata.getObjectInfos().size() > 0) {
                Response<?> response = runtimeServerAPI.compile(context);
            }
        } catch (RuntimeServerException ex) {
            Logger.getLogger(CodeGeneratorBackingBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void onSelectedProject(ValueChangeEvent e) throws DAOException, FacadeException {
        String value = (String) e.getNewValue();
        if (!value.equals("-")) {
            Project project = extProjectManager.getProjectByName((String) e.getNewValue());
            setProject(project);

            setParameters(extPropertyManager.getProjectParameters(project));
            setVariables(extPropertyManager.getProjectVariables(project));
            setTemplates(extTemplateManager.getTemplatesByPackage(project.getPackageTemplate()));

            newContext(parameters, variables);

        } else {
            newContext();
        }
    }

    /**
     * @return the projects
     */
    public List<Project> getProjects() throws FacadeException {
        if (getSession().getValue(PROJECTS) != null) {
            projects = (List<Project>) getSession().getValue(PROJECTS);
        } else {
            setProjects(projectManager.find());
        }
        return projects;
    }

    /**
     * @param projects the projects to set
     */
    public void setProjects(List<Project> projects) {
        this.projects = projects;
        getSession().setValue(PROJECTS, projects);
    }

    /**
     * @return the projectName
     */
//    public String getProjectName() {
//        if (getSession().getValue(getClass().getCanonicalName() + ".project") != null) {
//            projectName = getSession().getValue(getClass().getCanonicalName() + ".project");
//        }
//        return projectName;
//    }

//    /**
//     * @param projectName the projectName to set
//     */
//    public void setProjectName(String projectName) {
//        this.projectName = projectName;
//        getSession().setValue(getClass().getCanonicalName() + ".project", projectName);
//    }

    /**
     * @return the parameters
     */
    public List<Property> getParameters() throws DAOException {
        if (getSession().getValue(getClass().getCanonicalName() + ".parameters") != null) {
            parameters = getSession().getValue(getClass().getCanonicalName() + ".parameters");
        } else {
            Project project = getProject();
            if (project != null && project.getId() != null) {
                setParameters(extPropertyManager.getProjectParameters(project));
            }
        }
        return parameters;
    }

    /**
     * @param parameters the parameters to set
     */
    public void setParameters(List<Property> parameters) {
        this.parameters = parameters;
        getSession().setValue(getClass().getCanonicalName() + ".parameters", parameters);
    }

    /**
     * @return the variables
     */
    public List<Property> getVariables() throws DAOException {
        if (getSession().getValue(getClass().getCanonicalName() + ".variables") != null) {
            variables = getSession().getValue(getClass().getCanonicalName() + ".variables");
        } else {
            Project project = getProject();
            if (project != null && project.getId() != null) {
                setVariables(extPropertyManager.getProjectVariables(project));
            }
        }
        return variables;
    }

    /**
     * @param variables the variables to set
     */
    public void setVariables(List<Property> variables) {
        this.variables = variables;
        getSession().setValue(getClass().getCanonicalName() + ".variables", variables);
    }

    /**
     * @return the templates
     */
    public List<Template> getTemplates() throws FacadeException {
        templates = new ArrayList<Template>();
        if (getSession().getValue(templates.getClass().getCanonicalName() + ".templates") != null) {
            templates = getSession().getValue(templates.getClass().getCanonicalName() + ".templates");
        } else {
            Project project = getProject();
            if (project != null && project.getId() != null) {
                setTemplates(extTemplateManager.getTemplatesByPackage(project.getPackageTemplate()));
            }
        }
        return templates;
    }

    /**
     * @param templates the templates to set
     */
    public void setTemplates(List<Template> templates) {
        this.templates = templates;
        getSession().setValue(templates.getClass().getCanonicalName() + ".templates", templates);
    }

    private void getMathContextByTemplate(Template template, TemplateInfo templateInfo) throws FacadeException {
        List<Match> matchs = extMatchManager.getMatchByProject(getProject(), template);
        for (Match match : matchs) {
            MatchContext matchContext = new MatchContext();
            List<com.farmcode.console.api.model.MatchContext> mts = extMatchContextManager.getMatchContextByMatch(match);
            matchContext.put("prefix", match.getPrefix());
            matchContext.put("replace", match.getReplace());
            matchContext.put("relocate", match.getRelocate());
            matchContext.put("relocatePath", match.getRelocatePath());
            for (com.farmcode.console.api.model.MatchContext mt : mts) {
                matchContext.put(mt.getName(), mt.getValue());
            }
            templateInfo.getMatchContextCollection().add(matchContext);
        }
    }

//    /**
//     * @return the tablesRoot
//     */
//    public TreeNode getTablesRoot() throws FacadeException {
//        if(projectName != null){
//            projects = getProjects();
//            for (Project project : projects) {
//                if(project.getName().equals(projectName)){
//                    
//                    break;
//                }
//            }
//        }
//        return tablesRoot;
//    }
//
//    /**
//     * @param tablesRoot the tablesRoot to set
//     */
//    public void setTablesRoot(TreeNode tablesRoot) {
//        this.tablesRoot = tablesRoot;
//    }
}
